﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Globalization;
using LostLib.Programs.Properties;

namespace LostLib.Programs
{
	partial class PackageVersion : IFormattable, IEquatable<PackageVersion>
	{
		/// <summary>
		/// Determines whether this instance and another PackageVersion represents the same version. 
		/// </summary>
		/// <param name="other">An PackageVersion.</param>
		/// <returns>True if instances represent the same version.</returns>
		public bool Equals(PackageVersion other)
		{
			var version = other as PackageVersion;
			if (version == null) return false;
			return
				this.VersionString.Equals(version.VersionString);
		}

		/// <summary>
		/// Determines whether this instance and another object represents the same version. 
		/// </summary>
		/// <param name="obj">An object.</param>
		/// <returns>True if instances represent the same version.</returns>
		public override bool Equals(object obj)
		{
			var version = obj as PackageVersion;
			if (version == null) return false;
			return
				this.VersionString.Equals(version.VersionString);
		}
		/// <summary>
		/// Returns hash code for PackageVersion.
		/// </summary>
		/// <returns>Hash code.</returns>
		public override int GetHashCode()
		{
			return VersionString.GetHashCode();
		}

		/// <summary>
		/// Determines whether a local copy of version exists.
		/// </summary>
		public bool Cached
		{
			get
			{
				return File.Exists(LocalFileName);
			}
		}

		/// <summary>
		/// Gets a full file name for version local copy.
		/// </summary>
		public string LocalFileName
		{
			get { return Path.Combine(Settings.Default.PackageCache, VersionString); }
		}

		/// <summary>
		/// Returns all resolved dependancies of this version.
		/// </summary>
		public IEnumerable<PackageVersion> ResolvedDependancies
		{
			get
			{
				foreach (var dependancy in VersionDependancies)
				{
					if (dependancy.DependancyType != "newer") throw new NotSupportedException(dependancy.DependancyType);

					var installed = dependancy.Package.InstalledVersion;
					if ((installed != null) && (installed.Version >= dependancy.Version)) yield return installed;
				}
			}
		}
		/// <summary>
		/// Determines whether current verion is built-in.
		/// </summary>
		public bool IsBuiltIn
		{
			get
			{
				if (!VirtualPackage) return false;

				return VersionDependancies.Count == 0;
			}
		}

		internal static PackageVersion Parse(XmlNode versionNode)
		{
			var date = DateTime.Parse(
					versionNode.Attributes["date"].Value,
					CultureInfo.InvariantCulture.DateTimeFormat);
			var size = int.Parse(versionNode.Attributes["size"].Value, CultureInfo.InvariantCulture);
			bool virt = bool.Parse(versionNode.Attributes["virtual"].Value);
			var uri = versionNode.Attributes["uri"].Value;

			var version = new PackageVersion() {
				Uri = uri,
				Dependancy = false,
				Installed = false,
				SizeKiB = size,
				Version = date,
				VirtualPackage = virt,
			};

			version.VersionString = versionNode.Attributes["string"] != null
					? versionNode.Attributes["string"].Value
					: version.ToString(null, CultureInfo.InvariantCulture);


			return version;
		}

		#region IFormattable Members
		/// <summary>
		/// Gets PackageVersion's string representation.
		/// </summary>
		/// <returns>String representation of PackageVersion.</returns>
		public override string ToString()
		{
			return string.Format(CultureInfo.CurrentCulture, "{0}={1}",
				PackageName,
				Version.ToString("d", CultureInfo.CurrentCulture));
		}
		/// <summary>
		/// Gets PackageVersion's formatted string representation.
		/// </summary>
		/// <param name="format">Format string.</param>
		/// <param name="formatProvider">Format provider.</param>
		/// <returns>String representation of PackageVersion.</returns>
		public string ToString(string format, IFormatProvider formatProvider)
		{
			return //VersionString == null
				//? 
				  string.Format(formatProvider, "{0}={1}",
					PackageName,
					Version.ToString("d", formatProvider));
			//: VersionString;
		}

		#endregion
	}
}
